package cn.nawang.ebeim.server.thread;

import cn.nawang.ebeim.server.constants.Config;
import cn.nawang.ebeim.server.task.UploadFileTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;

/**
 * 循环去扫描指定目录下的文件，如果存在就将其移动到临时目录
 * Created by GanJc on 2015-11-11 10:36
 */
public abstract class FolderScanner implements Runnable {

    protected static final Logger LOG = LoggerFactory.getLogger(FolderScanner.class);

    @Override
    public void run() {
        try{
            //临时文件夹可能存在未上传的文件。开始前先扫描下临时文件夹
            scanTempDir();
        }catch (Exception e){
            LOG.info("扫描文件夹线程异常:"+e);
        }
        while (true) {
            try {
                File file = new File(getScanPath());
                LOG.debug("Scanning path：{}" , file);
                if(file.isDirectory()){
                    File[] dsList = file.listFiles();
                    for (int i = 0; i < dsList.length; i++) {
                        if (Config.TEMP_DS_FOLDER.equals(dsList[i].getName())) {
                            continue;
                        }
                        processingFile(dsList[i]);
                    }
                }
                Thread.sleep(Config.SCAN_INTERVAL);
            } catch (Exception ex) {
                LOG.info("扫描文件夹线程异常:"+ex);
            }
        }
    }

    private void scanTempDir() {
        String tempDirName = getScanPath() + File.separator + Config.TEMP_DS_FOLDER ;
        File tempDir = new File(tempDirName);
        if (tempDir.exists()&&tempDir.isDirectory()) {
            for (File file : tempDir.listFiles()) {
                if (file.isDirectory()){
                    for (File obj : file.listFiles()) {
                        String fileName = obj.getName();
                        if (fileName.startsWith(Config.UPLOAD_FILE_PREFIX)) {
                            UploadFileTask uploadFileTask = new UploadFileTask(obj.getAbsolutePath(), getFileType());
                            putIntoTaskQueue(uploadFileTask);
                        }
                    }
                }
            }
        }
    }

    /**
     * 对扫描到的数据源文件夹中的文件继续做操作
     * @param dsFolder 扫描到数据源文件夹
     */
    private void processingFile(File dsFolder) {
        if(!dsFolder.isDirectory()){
            return;
        }
        String fileType = getFileType();
        String scanPath = getScanPath();
        for (File file : dsFolder.listFiles()) {
            String fileName = file.getName();
            if (fileName.startsWith(Config.TEMP_FILE_PREFIX)) {
                //临时文件跳过
                continue;
            }else if(fileName.startsWith(Config.BREAK_POINT_PREFIX)){
                //断点续传文件 继续上传
                //提取原文件名
                String trueFileName = fileName.substring(fileName.lastIndexOf('_') + 1, fileName.length());
                //改成临时文件名
                String tempFileName = scanPath + File.separator + dsFolder.getName() + File.separator + Config.TEMP_FILE_PREFIX + trueFileName;
                //继续上传
                redoBreakPointTask(dsFolder.getName(), file, trueFileName, tempFileName);
            }else {
                //其他的为新上传文件,1移动到临时目录,2改名,3加入传输队列,等待上传至服务器
                String tempDirName = scanPath + File.separator + Config.TEMP_DS_FOLDER + File.separator + dsFolder.getName();
                File tempDir = new File(tempDirName);
                // 创建临时目录
                if (!tempDir.exists()) {
                    tempDir.mkdirs();
                }
                //改名
                File newFile = new File(tempDirName + File.separator + Config.UPLOAD_FILE_PREFIX + fileName);
                file.renameTo(newFile);
                LOG.info("扫描到新文件:{}，并且成功移动到临时目录:{}", fileName, tempDir);
                //放入传输队列,等待上传至服务器
                UploadFileTask uploadFileTask = new UploadFileTask(newFile.getAbsolutePath(), fileType);
                putIntoTaskQueue(uploadFileTask);
            }
        }

    }

    protected abstract void redoBreakPointTask(String dsId, File file,  String trueFileName, String tempFileName);

    /**
     * 放入传输队列
     * @param uploadFileTask
     */
    protected abstract void putIntoTaskQueue(UploadFileTask uploadFileTask);

    /**
     * 扫描的路径
     * @return
     */
    protected abstract String getScanPath();

    /**
     * 扫描的文件类型: 版本树文件或者数据文件
     * @return
     */
    protected abstract String getFileType();

}
